<template>
  <div :style="{width: data.config.width}" class="fm-form">
    <el-form
      ref="generateForm"
      :key="formKey"
      :class="{
        [data.config.customClass]: data.config.customClass?true: false,
        'no-label-form': data.config.labelWidth == 0
      }"
      :size="data.config.size"
      :model="models"
      :rules="rules"
      :label-position="data.config.labelPosition"
      :disabled="!edit"
      :label-width="data.config.labelWidth + 'px'"
    >

      <template v-for="item in data.list">
        <generate-col-item
          v-if="item.type == 'grid'"
          :key="item.key"
          :model.sync="models"
          :rules="rules"
          :element="item"
          :remote="remote"
          :blanks="blanks"
          :display="displayFields"
          :edit="edit"
          :remote-option="remoteOption"
          @input-change="onInputChange"
        >
          <template v-for="blank in blanks" v-slot:[blank.name]="scope">
            <slot :name="blank.name" :model="scope.model" />
          </template>
        </generate-col-item>

        <generate-tab-item
          v-else-if="item.type == 'tabs'"
          :key="item.key"
          :model.sync="models"
          :rules="rules"
          :element="item"
          :remote="remote"
          :blanks="blanks"
          :display="displayFields"
          :edit="edit"
          :remote-option="remoteOption"
          @input-change="onInputChange"
        >
          <template v-for="blank in blanks" v-slot:[blank.name]="scope">
            <slot :name="blank.name" :model="scope.model" />
          </template>
        </generate-tab-item>

        <generate-report
          v-else-if="item.type == 'report'"
          :key="item.key"
          :model.sync="models"
          :rules="rules"
          :element="item"
          :remote="remote"
          :blanks="blanks"
          :display="displayFields"
          :edit="edit"
          :remote-option="remoteOption"
          @input-change="onInputChange"
        >
          <template v-for="blank in blanks" v-slot:[blank.name]="scope">
            <slot :name="blank.name" :model="scope.model" />
          </template>
        </generate-report>

        <generate-form-item
          v-else
          :key="item.key"
          :models.sync="models"
          :rules="rules"
          :widget="item"
          :remote="remote"
          :blanks="blanks"
          :display="displayFields"
          :edit="edit"
          :remote-option="remoteOption"
          @input-change="onInputChange"
        >
          <template v-for="blank in blanks" v-slot:[blank.name]="scope">
            <slot :name="blank.name" :model="scope.model" />
          </template>
        </generate-form-item>
      </template>
    </el-form>
  </div>
</template>

<script>
import GenerateFormItem from './GenerateFormItem'
import GenerateColItem from './GenerateColItem'
import GenerateTabItem from './GenerateTabItem'
import GenerateReport from './GenerateReport'
import { loadJs } from '../util/index.js'
import _ from 'lodash'

export default {
  name: 'FmGenerateForm',
  components: {
    GenerateFormItem,
    GenerateColItem,
    GenerateTabItem,
    GenerateReport
  },
  props: {
    data: {
      type: Object,
      default: {
        'list': [],
        'config': {
          'labelWidth': 100,
          'labelPosition': 'right',
          'size': 'small',
          'customClass': '',
          'ui': 'element',
          'layout': 'horizontal',
          'labelCol': 3,
          width: '100%'
        }
      }
    },
    remote: {
      type: Object,
      default: () => ({})
    },
    value: {
      type: Object,
      default: () => ({})
    },
    edit: {
      type: Boolean,
      default: true
    },
    remoteOption: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      dataBindOptions:{},
      models: {},
      rules: {},
      blanks: [],
      displayFields: {},
      dataBindFields: [],
      generateShow: false,
      resetModels: {},
      formKey: new Date().getTime(),
      formValue: this.value
    }
  },
  watch: {

    data: {
      deep: true,
      handler(val) {
        this._initForm()
      }
    },
    value: {
      deep: true,
      handler(val) {
        this.reset();
        let s=_.cloneDeep(val);
        if(!_.isEmpty(this.dataBindOptions)){
          for(let k in s){
            let opts=this.dataBindOptions[k];
            if(opts && opts.multiple){
              s[k]=s[k].split(",")
            }
          }
        }
        this.models =s
      },
      immediate: true
    },
    models: {
      deep: true,
      handler(val) {
        this.formValue = { ...val }
      }
    }
  },
  created() {
    this._initForm()
  },
  mounted() {
  },
  methods: {
    _initForm() {
      if (Object.keys(this.data).length) {
        this.generateModel(this.data.list)
      } else {
        this.generateModel([])
      }

      this.resetModels = _.cloneDeep(this.models)
    },
    generateModel(genList) {
      window.sssform=this;
      for (let i = 0; i < genList.length; i++) {
        if (genList[i].type === 'grid') {
          this.displayFields[genList[i].model] = !genList[i].options.hidden

          genList[i].columns.forEach(item => {
            this.generateModel(item.list)
          })
        } else if (genList[i].type === 'tabs') {
          genList[i].tabs.forEach(item => {
            this.generateModel(item.list)
          })

          this.displayFields[genList[i].model] = !genList[i].options.hidden
        } else if (genList[i].type === 'report') {
          genList[i].rows.forEach(row => {
            row.columns.forEach(column => {
              this.generateModel(column.list)
            })
          })
        } else {
           this.dataBindOptions= this.dataBindOptions||{};
           this.dataBindOptions[genList[i].model]=genList[i].options;
          if (Object.keys(this.formValue).indexOf(genList[i].model) >= 0) {
            // 处理老版本没有dataBind值的情况，默认绑定数据
            if (Object.keys(genList[i].options).indexOf('dataBind') < 0 || genList[i].options.dataBind) {
              this.models[genList[i].model] = this.formValue[genList[i].model]
              this.dataBindFields.push(genList[i].model)

            }

            this.displayFields[genList[i].model] = !genList[i].options.hidden

            if (genList[i].type === 'blank') {
              this.blanks.push({
                name: genList[i].model
              })
            }
          } else {
            if (genList[i].type === 'blank') {
              // bound the default value
              if (Object.keys(genList[i].options).indexOf('dataBind') < 0 || genList[i].options.dataBind) {

                this.models[genList[i].model] = genList[i].options.defaultType === 'String' ? '' : (genList[i].options.defaultType === 'Object' ? {} : [])
                this.dataBindFields.push(genList[i].model)
              }
              this.displayFields[genList[i].model] = !genList[i].options.hidden

              this.blanks.push({
                name: genList[i].model
              })
            } else {
              if (Object.keys(genList[i].options).indexOf('dataBind') < 0 || genList[i].options.dataBind) {

                this.models[genList[i].model] = genList[i].type == 'table' ? [] : genList[i].options.defaultValue
                this.dataBindFields.push(genList[i].model)
              }
              this.displayFields[genList[i].model] = !genList[i].options.hidden
            }
          }

          genList[i].tableColumns && genList[i].tableColumns.length && genList[i].tableColumns.forEach(item => {
            if (item.type === 'blank') {
              this.blanks.push({
                name: item.model
              })
            }

            // 处理 rules
            if (this.rules[`${genList[i].model}.${item.model}`]) {
              this.rules[`${genList[i].model}.${item.model}`] = [
                ...this.rules[`${genList[i].model}.${item.model}`],
                ...item.rules.map(im => {
                  if (im.pattern) {
                    return { ...im, pattern: eval(im.pattern) }
                  } else {
                    return { ...im }
                  }
                })
              ]
            } else {
              this.rules[`${genList[i].model}.${item.model}`] = [
                ...item.rules.map(im => {
                  if (im.pattern) {
                    return { ...im, pattern: eval(im.pattern) }
                  } else {
                    return { ...im }
                  }
                })
              ]
            }
          })

          if (this.rules[genList[i].model]) {
            this.rules[genList[i].model] = [...this.rules[genList[i].model], ...genList[i].rules.map(item => {
              if (item.pattern) {
                return { ...item, pattern: eval(item.pattern) }
              } else {
                return { ...item }
              }
            })]
          } else {
            this.rules[genList[i].model] = [...genList[i].rules.map(item => {
              if (item.pattern) {
                return { ...item, pattern: eval(item.pattern) }
              } else {
                return { ...item }
              }
            })]
          }
        }
      }
    },
    _setDisabled(genList, fields, disabled) {
      for (let i = 0; i < genList.length; i++) {
        if (genList[i].type === 'grid') {
          genList[i].columns.forEach(item => {
            this._setDisabled(item.list, fields, disabled)
          })
        } else if (genList[i].type === 'tabs') {
          genList[i].tabs.forEach(item => {
            this._setDisabled(item.list, fields, disabled)
          })
        } else if (genList[i].type == 'report') {
          genList[i].rows.forEach(row => {
            row.columns.forEach(column => {
              this._setDisabled(column.list, fields, disabled)
            })
          })
        } else {
          if (fields.indexOf(genList[i].model) >= 0||fields.indexOf(genList[i].fieldCode)>= 0) {
            this.$set(genList[i].options, 'disabled', disabled)
          }
        }
      }
    },
    setItemDisabled(fields, disabledItem){
      this._setItemDisabled(this.data.list,fields,disabledItem);
    },
     _setItemDisabled(genList, fields, disabledItem) {
      for (let i = 0; i < genList.length; i++) {
        if (genList[i].type === 'grid') {
          genList[i].columns.forEach(item => {
            this._setItemDisabled(item.list, fields, disabledItem)
          })
        } else if (genList[i].type === 'tabs') {
          genList[i].tabs.forEach(item => {
            this._setItemDisabled(item.list, fields, disabledItem)
          })
        } else if (genList[i].type == 'report') {
          genList[i].rows.forEach(row => {
            row.columns.forEach(column => {
              this._setItemDisabled(column.list, fields, disabledItem)
            })
          })
        } else {
          if (fields.indexOf(genList[i].model) >= 0||fields.indexOf(genList[i].fieldCode)>= 0) {
            this.$set(genList[i].options, 'disabledItems', disabledItem)
          }
        }
      }
    },
    validate() { // add
      return new Promise((resolve, reject) => {
        this.$refs.generateForm.validate(valid => {
          if (valid) {
            resolve(valid)
          }
          resolve(false)
        })
      })
    },
    getData4Search() {
      const resData = {}
      Object.keys(this.models).forEach(key => {
        if (this.dataBindFields.indexOf(key) >= 0) {
          let val = this.models[key]
          if (Object.prototype.toString.call(val) == '[object Array]') { val = val.join(',') }
          resData[key] = val
        }
      })
      return JSON.parse(JSON.stringify(resData));
    },
    getData() {
      return new Promise((resolve, reject) => {
        this.$refs.generateForm.validate(valid => {
          if (valid) {
            const resData = {}
            Object.keys(this.models).forEach(key => {
              if (this.dataBindFields.indexOf(key) >= 0) {
                let val = this.models[key]
                if (Object.prototype.toString.call(val) == '[object Array]') { val = val.join(',') }
                resData[key] = val
              }
            })
            resolve(JSON.parse(JSON.stringify(resData)))
            // resolve(resData)
          } else {
            reject(new Error(this.$t('fm.message.validError')).message)
          }
        })
      })
    },
    reset() {
      this.setData(_.cloneDeep(this.resetModels))
      this.formKey = new Date().getTime()
    },
    onInputChange(value, field) {
      this.$emit('on-change', field, value, this.models)
      this.$emit(`on-${field}-change`, value)
    },
    display(fields) {
      Object.keys(this.displayFields).forEach(key => {
        if (fields.indexOf(key) >= 0) {
          this.$set(this.displayFields, key, true)
        }
      })
      this.displayFields = { ...this.displayFields }
    },
    hide(fields) {
      Object.keys(this.displayFields).forEach(key => {
        if (fields.indexOf(key) >= 0) {
          this.$set(this.displayFields, key, false)
        }
      })

      this.displayFields = { ...this.displayFields }
    },
    disabled(fields, disabled) {
      this._setDisabled(this.data.list, fields, disabled)
    },
    refresh() {
    },
    setData(value) {
      this.models = { ...this.models, ...value }
    }
  }
}
</script>

<style  scoped>
.el-aside ::deep{
  padding:0px
}
.fm2-main .el-aside {
     padding:0px

}
</style>
